"""
Python基础学习 - 魔术方法示例代码
=============================

本文件展示了Python中常用的魔术方法：
1. __init__ - 初始化对象
2. __str__ - 对象的字符串表示
3. __repr__ - 对象的官方字符串表示
4. __add__ - 加法运算
5. __eq__ - 相等比较
6. __len__ - 长度
7. __getitem__ - 索引访问

魔术方法是Python中以双下划线开头和结尾的特殊方法。
它们允许我们自定义类的行为，使其支持Python的内置操作。
在实际工作中，魔术方法常用于创建更Pythonic的API。
例如，在数据科学库中，向量或矩阵类会实现__add__、__mul__等方法，
使用户可以使用+、*等运算符进行数学运算。
"""

# 魔术方法示例
# 魔术方法是Python中以双下划线开头和结尾的特殊方法
# 它们允许我们自定义类的行为，使其支持Python的内置操作
class Vector:
    """向量类，演示常用魔术方法

    通过实现不同的魔术方法，让Vector对象支持各种Python内置操作。
    """
    
    # __init__方法已在前面详细解释
    def __init__(self, x, y):
        """初始化向量

        Args:
            x (float): x分量
            y (float): y分量
        """
        self.x = x
        self.y = y
    
    # __str__方法 - 定义对象的字符串表示
    # 当使用print()或str()函数时调用
    def __str__(self):
        """字符串表示 - 用于print()和str()函数

        Returns:
            str: 向量的字符串表示
        """
        return f"Vector({self.x}, {self.y})"
    
    # __repr__方法 - 定义对象的官方字符串表示
    # 当在交互式解释器中直接输入对象或使用repr()函数时调用
    def __repr__(self):
        """官方字符串表示 - 用于调试和开发

        Returns:
            str: 向量的官方字符串表示
        """
        return f"Vector(x={self.x}, y={self.y})"
    
    # __add__方法 - 定义加法运算
    # 当使用+运算符时调用
    def __add__(self, other):
        """加法运算 - 支持向量相加

        Args:
            other (Vector): 另一个向量
            
        Returns:
            Vector: 相加后的结果向量
        """
        # 检查other是否为Vector类型
        if isinstance(other, Vector):
            # 返回新的Vector对象，其分量为两个向量分量之和
            return Vector(self.x + other.x, self.y + other.y)
        # 如果other不是Vector类型，返回NotImplemented
        # Python会尝试其他解决方案或抛出TypeError
        return NotImplemented
    
    # __eq__方法 - 定义相等比较
    # 当使用==运算符时调用
    def __eq__(self, other):
        """相等比较 - 支持向量相等判断

        Args:
            other (Vector): 另一个向量
            
        Returns:
            bool: 相等返回True，否则返回False
        """
        # 检查other是否为Vector类型
        if isinstance(other, Vector):
            # 当两个向量的分量都相等时，认为它们相等
            return self.x == other.x and self.y == other.y
        # 如果other不是Vector类型，认为不相等
        return False
    
    # __len__方法 - 定义长度
    # 当使用len()函数时调用
    def __len__(self):
        """长度 - 返回向量模的整数部分

        Returns:
            int: 向量模的整数部分
        """
        # 计算向量的模（长度）并返回整数部分
        return int((self.x**2 + self.y**2)**0.5)
    
    # __getitem__方法 - 定义索引访问
    # 当使用[]运算符访问元素时调用
    def __getitem__(self, index):
        """索引访问 - 支持通过索引访问向量分量

        Args:
            index (int): 索引，0表示x分量，1表示y分量
            
        Returns:
            float: 对应分量的值
            
        Raises:
            IndexError: 索引超出范围时抛出异常
        """
        if index == 0:
            return self.x  # 返回x分量
        elif index == 1:
            return self.y  # 返回y分量
        else:
            # 索引必须是0或1，否则抛出IndexError异常
            raise IndexError("索引必须是0或1")

def magic_methods_demo():
    print("\n=== 魔术方法示例 ===")
    
    # 创建向量对象
    v1 = Vector(3, 4)
    v2 = Vector(1, 2)
    
    # __str__ 和 __repr__
    # print()调用__str__方法，repr()调用__repr__方法
    print(f"v1: {v1}")        # 调用__str__方法
    print(f"v2: {repr(v2)}")  # 调用__repr__方法
    
    # __add__
    # +运算符调用__add__方法
    v3 = v1 + v2  # 等价于v1.__add__(v2)
    print(f"v1 + v2 = {v3}")
    
    # __eq__
    # ==运算符调用__eq__方法
    print(f"v1 == v2: {v1 == v2}")  # 等价于v1.__eq__(v2)
    print(f"Vector(3, 4) == Vector(3, 4): {Vector(3, 4) == Vector(3, 4)}")
    
    # __len__
    # len()函数调用__len__方法
    print(f"v1的长度: {len(v1)}")  # 等价于v1.__len__()
    
    # __getitem__
    # []运算符调用__getitem__方法
    print(f"v1的x分量: {v1[0]}")  # 等价于v1.__getitem__(0)
    print(f"v1的y分量: {v1[1]}")  # 等价于v1.__getitem__(1)

# 主函数 - 程序的入口点
if __name__ == "__main__":
    magic_methods_demo()